const Executor = function() {
    this.status = "init",
    this.interval = undefined,
    this.scheduler = undefined,
    this.pipeline = {},
    //this.runtime = runtime.instance(),
    this.comfirm = function(flowId, before, after) {
        if (!this.pipeline[flowId]) {
            return
        }
        this.pipeline[flowId]["before"] = before || (() => console.log("任务开始:" + flowId))
        this.pipeline[flowId]["after"] = after || (() => console.log("任务结束:" + flowId))
        this.pipeline[flowId]["status"] = "pending"
    },
    this.init = function(flowId) {
        if (!this.pipeline[flowId]) {
            this.pipeline[flowId] = {
                status: "init",
                context: {},
                tasks: {},
                before: (() => console.log("任务开始:" + flowId)),
                after: (() => console.log("任务结束:" + flowId))
            }
        }
        return this.pipeline[flowId]
    },
    this.submit = function(flowId, tasks) {
        let pipeline = this.init(flowId)
        for (let task of tasks) {
            console.log(pipeline.tasks[task.name])
            if (pipeline.tasks[task.name]) {
                break
            }
            if (task.depend == "default") {
                let taskKeys = Object.keys(pipeline.tasks) || [undefined]
                task.depend = taskKeys[taskKeys.length - 1]
            }
            pipeline.tasks[task.name] = task
        }
        pipeline.status = "pending"
        console.info(JSON.stringify(pipeline.tasks))
    },
    this.registerScheduler = function(scheduler) {
        this.scheduler = scheduler
    },
    this.remove = function(flowId, name) {
        if (!this.pipeline[flowId] || !this.pipeline[flowId]["tasks"][name]) {
            return
        }
        delete this.pipeline[flowId]["tasks"][name]
    },
    this.release = function() {
        clearInterval(this.interval)
    },
    this.execute = function() {
        if (this.status == "running") {
            let flowIds = this.pipeline["_subtask"] ? ["_subtask"] : Object.keys(this.pipeline)
            if (!flowIds || flowIds.length == 0 || !flowIds[0]) {
                return
            }
            let status = this.pipeline[flowIds[0]]["status"]
            if (status == "init") {
                return
            }
            if (this.completed(flowIds[0])) {
                //this.pipeline[flowIds[0]]["after"]()
                delete this.pipeline[flowIds[0]]
                return
            }
            if (status == 'pending') {
                this.pipeline[flowIds[0]]["status"] = "processing"
                //this.pipeline[flowIds[0]]["before"]()
            }
            let tasks = this.pipeline[flowIds[0]]["tasks"]
            let context = this.pipeline[flowIds[0]]["context"]
            for(let name in tasks) {
                let task = tasks[name]
                if (task.completed()) {
                    continue
                }
                if (task.depend && tasks[task.depend].next != -1) {
                    continue
                }
                if (!task.ready()) {
                    continue
                }
                threads.start(() => task.run(context))
            }
        }  
    },
    this.completed = function(flowId) {
        if (!this.pipeline[flowId]) {
            return true
        }
        for(let name in this.pipeline[flowId]["tasks"]) {
            let task = this.pipeline[flowId]["tasks"][name]
            if (task && !task.completed()) {
                return false
            }
        }
        return true
    },
    this.switch = function() {
        if (this.status == "running") {
            this.status = "pause"
        } else {
            this.status = "running"
        }
        return this.status == "running"
    }
    this.start = function() {
        this.status = "running"
    },
    this.pause = function() {
        this.status = "pause"
    }
}

exports.createExecutor = () => {
    let executor = new Executor()
    executor.interval =setInterval(() => executor.execute(), 200)
    return executor
}